Add memory barriers to console ring accesses. Similar to what
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 12 Oct 2005 20:10:14 +0000 (21:10 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 12 Oct 2005 20:10:14 +0000 (21:10 +0100)
Rusty uses for xenbus messaging.

Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c
tools/console/daemon/io.c

index 0b37773575f05ef513cdb215b951b9b0bbff2daa..9dcb60b5c84717f0ef74fc502a897dc74f527fbd 100644 (file)
@@ -34,14 +34,18 @@ int xencons_ring_send(const char *data, unsigned len)
 {
        int sent = 0;
        struct xencons_interface *intf = xencons_interface();
+       XENCONS_RING_IDX cons, prod;
 
-       while ((sent < len) &&
-              (intf->out_prod - intf->out_cons) < sizeof(intf->out)) {
-               intf->out[MASK_XENCONS_IDX(intf->out_prod, intf->out)] =
-                       data[sent];
-               intf->out_prod++;
-               sent++;
-       }
+       cons = intf->out_cons;
+       prod = intf->out_prod;
+       mb();
+       BUG_ON((prod - cons) > sizeof(intf->out));
+
+       while ((sent < len) && ((prod - cons) < sizeof(intf->out)))
+               intf->out[MASK_XENCONS_IDX(prod++, intf->out)] = data[sent++];
+
+       wmb();
+       intf->out_prod = prod;
 
        /* Use evtchn: this is called early, before irq is set up. */
        notify_remote_via_evtchn(xen_start_info->console_evtchn);
@@ -52,16 +56,23 @@ int xencons_ring_send(const char *data, unsigned len)
 static irqreturn_t handle_input(int irq, void *unused, struct pt_regs *regs)
 {
        struct xencons_interface *intf = xencons_interface();
+       XENCONS_RING_IDX cons, prod;
 
-       while (intf->in_cons != intf->in_prod) {
+       cons = intf->in_cons;
+       prod = intf->in_prod;
+       mb();
+       BUG_ON((prod - cons) > sizeof(intf->in));
+
+       while (cons != prod) {
                if (xencons_receiver != NULL)
                        xencons_receiver(
-                               intf->in + MASK_XENCONS_IDX(intf->in_cons,
-                                                           intf->in),
+                               intf->in + MASK_XENCONS_IDX(cons++, intf->in),
                                1, regs);
-               intf->in_cons++;
        }
 
+       wmb();
+       intf->in_cons = cons;
+
        return IRQ_HANDLED;
 }
 
index fc772b7580e69225c247c7aacf799f28dc47b035..9039a96525a9cb93c51b2a4db7d24946e97c12f5 100644 (file)
@@ -79,44 +79,43 @@ static void evtchn_notify(struct domain *dom)
 static void buffer_append(struct domain *dom)
 {
        struct buffer *buffer = &dom->buffer;
-       size_t size;
-       XENCONS_RING_IDX oldcons;
-       int notify = 0;
+       XENCONS_RING_IDX cons, prod, size;
        struct xencons_interface *intf = dom->interface;
 
-       while ((size = (intf->out_prod - intf->out_cons)) != 0) {
-               notify = 1;
+       cons = intf->out_cons;
+       prod = intf->out_prod;
+       mb();
 
-               if ((buffer->capacity - buffer->size) < size) {
-                       buffer->capacity += (size + 1024);
-                       buffer->data = realloc(buffer->data, buffer->capacity);
-                       if (buffer->data == NULL) {
-                               dolog(LOG_ERR, "Memory allocation failed");
-                               exit(ENOMEM);
-                       }
-               }
-
-               oldcons = intf->out_cons;
-               while ((intf->out_cons - oldcons) < size) {
-                       buffer->data[buffer->size] = intf->out[
-                               MASK_XENCONS_IDX(intf->out_cons, intf->out)];
-                       buffer->size++;
-                       intf->out_cons++;
-               }
+       size = prod - cons;
+       if ((size == 0) || (size > sizeof(intf->out)))
+               return;
 
-               if (buffer->max_capacity &&
-                   buffer->size > buffer->max_capacity) {
-                       memmove(buffer->data + (buffer->size -
-                                               buffer->max_capacity),
-                               buffer->data, buffer->max_capacity);
-                       buffer->data = realloc(buffer->data,
-                                              buffer->max_capacity);
-                       buffer->capacity = buffer->max_capacity;
+       if ((buffer->capacity - buffer->size) < size) {
+               buffer->capacity += (size + 1024);
+               buffer->data = realloc(buffer->data, buffer->capacity);
+               if (buffer->data == NULL) {
+                       dolog(LOG_ERR, "Memory allocation failed");
+                       exit(ENOMEM);
                }
        }
 
-       if (notify)
-               evtchn_notify(dom);
+       while (cons != prod)
+               buffer->data[buffer->size++] = intf->out[
+                       MASK_XENCONS_IDX(cons++, intf->out)];
+
+       mb();
+       intf->out_cons = cons;
+       evtchn_notify(dom);
+
+       if (buffer->max_capacity &&
+           buffer->size > buffer->max_capacity) {
+               memmove(buffer->data + (buffer->size -
+                                       buffer->max_capacity),
+                       buffer->data, buffer->max_capacity);
+               buffer->data = realloc(buffer->data,
+                                      buffer->max_capacity);
+               buffer->capacity = buffer->max_capacity;
+       }
 }
 
 static bool buffer_empty(struct buffer *buffer)
@@ -419,10 +418,14 @@ static void handle_tty_read(struct domain *dom)
        char msg[80];
        int i;
        struct xencons_interface *intf = dom->interface;
-       XENCONS_RING_IDX filled = intf->in_prod - intf->in_cons;
+       XENCONS_RING_IDX cons, prod;
+
+       cons = intf->in_cons;
+       prod = intf->in_prod;
+       mb();
 
-       if (sizeof(intf->in) > filled)
-               len = sizeof(intf->in) - filled;
+       if (sizeof(intf->in) > (prod - cons))
+               len = sizeof(intf->in) - (prod - cons);
        if (len > sizeof(msg))
                len = sizeof(msg);
 
@@ -441,10 +444,11 @@ static void handle_tty_read(struct domain *dom)
                }
        } else if (domain_is_valid(dom->domid)) {
                for (i = 0; i < len; i++) {
-                       intf->in[MASK_XENCONS_IDX(intf->in_prod, intf->in)] =
+                       intf->in[MASK_XENCONS_IDX(prod++, intf->in)] =
                                msg[i];
-                       intf->in_prod++;
                }
+               wmb();
+               intf->in_prod = prod;
                evtchn_notify(dom);
        } else {
                close(dom->tty_fd);